package com.atguigu.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.DictFeignClient;
import com.atguigu.model.cmn.Dict;
import com.atguigu.model.hosp.Hospital;
import com.atguigu.repository.HospitalRepository;
import com.atguigu.service.HospitalService;
import com.atguigu.utils.RedisUtil;
import com.atguigu.vo.hosp.HospitalQueryVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.*;
/*
 * 在Spring Data中使用MongoDB时，插入数据会添加一个_class字段，
 * 这个字段是用来映射POJO的
 *
 * 例如如果一个实体类的属性为 a b c
 *
 * 对应的数据库字段为 a b c _class
 *
 * 而使用ExampleMatcher，默认情况下会匹配所有字段（包括_class），因此，如果实体类的
 * 包名改变了，_class字段就不会匹配，这样就无法正确地得到查询结果
 *
 *
 * 解决方法：
 * 使用ExampleMatcher时，使用withIgnorePaths方法将_class字段过滤掉
 * .withIgnorePaths("_class")
 *
 * 参考：https://www.cnblogs.com/6b7b5fc3/p/14120890.html
 */
@Service
@Slf4j
public class HospitalServiceImpl implements HospitalService {

    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private DictFeignClient dictFeignClient;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void save(Map<String, Object> paramMap) {
        //把参数map集合转换JSON字符串的形式
        String mapString = JSONObject.toJSONString(paramMap);
        //把参数map集合转换JSON对象 Hospital
        Hospital hospital = JSONObject.parseObject(mapString, Hospital.class);

        //判断是否存在数据（根据Hospital中的hoscode字段来查询文档是否存在）
        String hoscode = hospital.getHoscode();
        Hospital hospitalExist = hospitalRepository.findHospitalByHoscode(hoscode);

        //根据hosCode获取医院信息，如果有这个医院就更新信息，没有就添加信息
        //如果存在，进行修改
        if(hospitalExist != null) {
            hospital.setStatus(hospitalExist.getStatus());
            hospital.setCreateTime(hospitalExist.getCreateTime());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);
        } else {//如果不存在，进行添加
            hospital.setStatus(0);
            hospital.setCreateTime(new Date());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);
        }
    }

    //从Mongodb中获取hoscode
    @Override
    public Hospital getByHoscode(String hoscode) {
        //根据医院编号查询Hospital实例
        Hospital hospital = hospitalRepository.findHospitalByHoscode(hoscode);
        return hospital;
    }


    //医院列表(条件查询分页)
    @Override
    public Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo) {
        //创建pageable对象
        Pageable pageable = PageRequest.of(page - 1,limit);
        //创建条件匹配器
        ExampleMatcher matcher = ExampleMatcher.matching()//构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)//改变默认字符串匹配方式：模糊查询 （CONTAINING：匹配包含模式的字符串）
                //Spring Data中使用MongoDB时，插入数据会添加一个_class字段，匹配时需要忽略掉
                .withIgnorePaths("_class")
                .withIgnoreCase(true);//改变默认大小写忽略方式：忽略大小写
        //hospitalSetQueryVo转换Hospital对象
        Hospital hospital = new Hospital();
        BeanUtils.copyProperties(hospitalQueryVo,hospital);

        //创建对象
        Example<Hospital> example = Example.of(hospital,matcher);

        //调用方法实现查询
        Page<Hospital> pages = hospitalRepository.findAll(example, pageable);
//        List<Hospital> content = pages.getContent();
//        for (Hospital hospital1 : content) {
//            System.out.println("===>" + hospital1);
//        }

        //获取查询list集合，遍历进行医院等级封装（item代表一个hospital实例）
        // 在原有hospital实例的基础上添加省、市、区等信息
        pages.getContent().stream().forEach(item -> {
            this.setHospitalHosType(item);
        });

        return pages;
    }

    //更新医院上线状态
    @Override
    public void updateStatus(String id, Integer status) {
        //根据id查询医院信息（mongodb中的id是自动生成的，findById返回的是Optional实例）
        Hospital hospital = hospitalRepository.findById(id).get();
        //将查询出的医院信息的状态修改，同时更新修改时间
        hospital.setStatus(status);
        hospital.setUpdateTime(new Date());
        hospitalRepository.save(hospital);//将更新后的实例添加
    }

    @Override
    public Map<String, Object> getHospById(String id) {
        Map<String, Object> result = new HashMap<>();
        //根据id获取医院信息后，在得到医院信息中的医院等级、省、市、区的信息
        Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
        //医院基本信息（包含医院等级）
        result.put("hospital",hospital);
        //单独处理更直观（预约信息）
        result.put("bookingRule", hospital.getBookingRule());
        //不需要重复返回
        hospital.setBookingRule(null);
        return result;
    }

    //获取医院名称
    @Override
    public String getHospName(String hoscode) {
        Hospital hospital = hospitalRepository.findHospitalByHoscode(hoscode);
        if(hospital != null) {
            return hospital.getHosname();
        }
        return null;
    }

    //根据医院名称查询
    @Override
    public List<Hospital> findByHosname(String hosname) {
        return hospitalRepository.findHospitalByHosnameLike(hosname);//模糊查询
    }

    //根据医院编号获取医院预约挂号详情
    @Override
    public Map<String, Object> item(String hoscode) {
        Map<String, Object> result = new HashMap<>();
        //医院详情（从Mongodb中获取hoscode）
        Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
        result.put("hospital", hospital);
        //预约规则
        result.put("bookingRule", hospital.getBookingRule());
        //预约规则不需要重复返回
        hospital.setBookingRule(null);
        return result;
    }

    //获取查询list集合，遍历进行医院等级封装
    private Hospital setHospitalHosType(Hospital hospital) {

        List<String> params = Arrays.asList(hospital.getHostype(), hospital.getProvinceCode(), hospital.getCityCode(), hospital.getDistrictCode());

        String hostypeString = "";
        String provinceString = "";
        String cityString = "";
        String districtString = "";

        //字典数据缓存
        if (redisUtil.getValByKey(hospital.getHostype()) != null &&
            redisUtil.getValByKey(hospital.getProvinceCode()) != null &&
            redisUtil.getValByKey(hospital.getCityCode()) != null &&
            redisUtil.getValByKey(hospital.getDistrictCode()) != null) {

            hostypeString = redisUtil.getValByKey(hospital.getHostype()).toString();
            provinceString = redisUtil.getValByKey(hospital.getProvinceCode()).toString();
            cityString = redisUtil.getValByKey(hospital.getCityCode()).toString();
            districtString = redisUtil.getValByKey(hospital.getDistrictCode()).toString();
        } else {
            List<Map<String, Dict>> dictMapList = dictFeignClient.getDictMapByVal(params);
            if (CollectionUtil.isEmpty(dictMapList)) {
                log.warn("字典数据为空，医院信息：{}", hospital);
                return null;
            }

            Map<String, String> resultMap = new HashMap<>();
            for (Map<String, Dict> dictMap : dictMapList) {
                if (dictMap.containsKey(hospital.getHostype())) {
                    Dict dict = dictMap.get(hospital.getHostype());
                    if (dict != null && StringUtils.isNotEmpty(dict.getDictCode()) &&
                            dict.getDictCode().equals("Hostype")) {
                        resultMap.put(hospital.getHostype(), dict.getName());
                    }
                }
                if (dictMap.containsKey(hospital.getProvinceCode())) {
                    Dict dict = dictMap.get(hospital.getProvinceCode());
                    if (dict != null) {
                        resultMap.put(hospital.getProvinceCode(), dict.getName());
                    }
                }
                if (dictMap.containsKey(hospital.getCityCode())) {
                    Dict dict = dictMap.get(hospital.getCityCode());
                    if (dict != null) {
                        resultMap.put(hospital.getCityCode(), dict.getName());
                    }
                }
                if (dictMap.containsKey(hospital.getDistrictCode())) {
                    Dict dict = dictMap.get(hospital.getDistrictCode());
                    if (dict != null) {
                        resultMap.put(hospital.getDistrictCode(), dict.getName());
                    }
                }
            }

            hostypeString = resultMap.get(hospital.getHostype());
            provinceString = resultMap.get(hospital.getProvinceCode());
            cityString = resultMap.get(hospital.getCityCode());
            districtString = resultMap.get(hospital.getDistrictCode());

            //缓存过期时间为半小时
            redisUtil.setKeyVal(hospital.getHostype(), hostypeString, 1800L);
            redisUtil.setKeyVal(hospital.getProvinceCode(), provinceString, 1800L);
            redisUtil.setKeyVal(hospital.getCityCode(), cityString, 1800L);
            redisUtil.setKeyVal(hospital.getDistrictCode(), districtString, 1800L);

            //根据dictCode和value获取医院等级以及省、市、区名称（查询数据编号为Hostype（医院）的记录）
//        String hostypeString = dictFeignClient.getName("Hostype", hospital.getHostype());
//        //这里最好加个缓存
//        //查询省 市  地区
//        String provinceString = dictFeignClient.getName(hospital.getProvinceCode());
//        String cityString = dictFeignClient.getName(hospital.getCityCode());
//        String districtString = dictFeignClient.getName(hospital.getDistrictCode());
        }

        hospital.getParam().put("fullAddress", provinceString+cityString+districtString);
        hospital.getParam().put("hostypeString", hostypeString);
        return hospital;
    }
}

